package system

import (
	"a-admin/web/resp"
	"a-common/constant"
	"a-common/myerr"
	"a-system/domain/entity"
	"a-system/service"
	"fmt"
	"strconv"
	"sync"

	"github.com/gofiber/fiber/v2"
)

var (
	userControllerTemp  *UserController
	sysUserService      = service.NewSysUserService()
	ruserControllerOnce sync.Once
)

type UserController struct{}

func NewSysUserController() *UserController {
	ruserControllerOnce.Do(func() {
		userControllerTemp = &UserController{}
	})
	return userControllerTemp
}

// List 分页
func (m *UserController) List(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.QueryParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	err := args.Validator()
	if err != nil {
		return err
	}

	pageVo, err := sysUserService.List(&args)
	if err != nil {
		return err
	}
	return resp.Resp(c, pageVo)
}

// Export 导出
func (m *UserController) Export(c *fiber.Ctx) error {
	var args entity.UserDto
	err := c.QueryParser(&args)
	if err != nil {
		return myerr.ERR_SYS_ARGS
	}

	f, err := sysUserService.Export(&args)
	if err != nil {
		return err
	}
	c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, "用户表.xlsx"))
	err = f.Write(c.Response().BodyWriter())
	if err != nil {
		return err
	}
	return nil
}

// ImportTemplate 获取导入模板
func (m *UserController) ImportTemplate(c *fiber.Ctx) error {
	return c.SendFile("./uploads/template/user_temp.xlsx")
}

// ImportData 导入
func (m *UserController) ImportData(c *fiber.Ctx) error {
	updateSupport := c.QueryInt("updateSupport")

	// 获取上传的文件
	file, err := c.FormFile("file")
	if err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)

	msg, err := sysUserService.Import(file, updateSupport, user.Account)
	if err != nil {
		return err
	}

	return resp.Resp(c, fiber.Map{
		"msg": msg,
	})
}

// Get 查
func (m *UserController) Get(c *fiber.Ctx) error {
	userId := c.Params("id")
	user := resp.GetUser(c)

	mp, err := sysUserService.Get(userId, user.Uid)
	if err != nil {
		return err
	}
	return resp.Resp(c, mp)
}

// Del 删
func (m *UserController) Del(c *fiber.Ctx) error {
	ids := c.Params("ids")
	if ids == "" {
		return myerr.ERR_SYS_ARGS
	}
	_, err := sysUserService.Del(ids)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// Add 增
func (m *UserController) Add(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.BodyParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	args.UserId = 0
	user := resp.GetUser(c)

	err := sysUserService.Add(&args, user.Uid)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// Edit 改
func (m *UserController) Edit(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.BodyParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)
	args.UpdatedBy = user.Account
	// 不允许操作根用户
	if args.UserId == constant.ADMIN_ID && user.Uid != constant.ADMIN_ID {
		return myerr.ERR_SYS_403
	}

	err := sysUserService.Edit(&args, user.Uid)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// ChangeStatus 切换状态
func (m *UserController) ChangeStatus(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.BodyParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)
	if args.UserId == constant.ADMIN_ID {
		return myerr.ERR_SYS_403
	}

	_, err := sysUserService.ChangeStatus(&args, user.Uid, user.Account)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// ResetPwd 重置密码
func (m *UserController) ResetPwd(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.BodyParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)
	args.UpdatedBy = user.Account

	_, err := sysUserService.UpdatePwd(&args, user.Uid, user.Account)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// UpdatePwd 修改密码
func (m *UserController) UpdatePwd(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.QueryParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)
	args.UpdatedBy = user.Account
	// 校验参数
	if args.OldPassword == args.NewPassword {
		return myerr.ERR_SYS_ARGS
	}

	_, err := sysUserService.UpdatePwd(&args, user.Uid, user.Account)
	if err != nil {
		return err
	}
	return resp.Ok(c)
}

// Avatar 头像上传
func (m *UserController) Avatar(c *fiber.Ctx) error {
	// 获取上传的文件
	file, err := c.FormFile("avatarfile")
	if err != nil {
		return err
	}
	user := resp.GetUser(c)

	// 更新用户头像路径
	path, err := sysUserService.Avatar(file, user.Uid, user.Account)
	if err != nil {
		return err
	}

	// 拼接返回文件访问路径
	return resp.Resp(c, fiber.Map{
		"imgUrl": path,
	})
}

// GetAvatar 获取头像
func (m *UserController) GetAvatar(c *fiber.Ctx) error {
	// 获取下载文件的路径
	filename := c.Params("*")
	filepath := "./uploads/profile/avatar/" + filename

	// 读取文件内容
	// file, err := os.ReadFile(filepath)
	// if err != nil {
	// 	res.ServerFail(c, res.FILE_ERR_READ, err)
	// }

	// 设置响应头，告诉浏览器这是一个可下载的文件
	// c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))

	// return c.Send(file)
	return c.SendFile(filepath)
}

// DeptTree 获取部门树
func (m *UserController) DeptTree(c *fiber.Ctx) error {
	v, err := sysUserService.DeptTree()
	if err != nil {
		return err
	}
	return resp.Resp(c, v)
}

// AuthRole 根据用户编号获取授权角色
func (m *UserController) AuthRole(c *fiber.Ctx) error {
	uId := c.Params("id")
	// 将字符串转换为int64
	userId, err := strconv.ParseInt(uId, 10, 64)
	if err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)

	mp, err := sysUserService.AuthRole(userId, user.Uid)
	if err != nil {
		return err
	}
	return resp.Resp(c, mp)
}

// InsertAuthRole 用户授权角色
func (m *UserController) InsertAuthRole(c *fiber.Ctx) error {
	var args entity.UserDto
	if err := c.QueryParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	user := resp.GetUser(c)

	// 更新用户角色
	if err := sysUserService.InsertAuthRole(&args, user.Uid); err != nil {
		return err
	}
	return resp.Ok(c)
}

// Profile 查询用户个人信息
func (m *UserController) Profile(c *fiber.Ctx) error {
	user := resp.GetUser(c)
	info, err := sysUserService.Profile(user.Uid)
	if err != nil {
		return err
	}
	return resp.Resp(c, info)
}

// GetSelectList 获取用户下拉列表
func (m *UserController) GetSelectList(c *fiber.Ctx) error {
	list, err := sysUserService.GetSelectList()
	if err != nil {
		return err
	}
	return resp.Resp(c, list)
}
